import MapboxDraw from '@mapbox/mapbox-gl-draw'
import '@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css'
import { Message } from 'element-ui'
import emitter from '@/utils/event-bus'
// import styles from '@/utils/draw-style/styles.js' // 自定义样式不完整，缺少顶点样式

class DrawingManager {
  constructor() {
    this.map = null
    this.draw = null
    this.isDrawingMode = false
    this.currentDrawingConfig = null
    this.controlsContainer = null
    this.initialized = false
  }

  init(map) {
    if (this.initialized && this.draw) {
      console.log('DrawingManager already initialized, resetting...')
      // Clean up existing instance before reinitializing
      this.cleanup()
    }
    
    this.map = map
    
    console.log('DrawingManager.init called with map:', map)
    console.log('Map loaded state:', map.loaded())
    
    // Check if MapboxDraw sources already exist from another instance
    if (map.getSource('mapbox-gl-draw-cold')) {
      console.warn('MapboxDraw sources already exist on map, need to handle this properly')
      // Don't try to remove sources directly as they may be in use
      // Instead, we'll let MapboxDraw handle this when we add the control
    }
    
    // Initialize MapboxDraw
    try {
      this.draw = new MapboxDraw({
        keybindings: true, // Enable keyboard shortcuts
        touchEnabled: false,
        boxSelect: true,
        clickBuffer: 2, // Allow easier selection of features
        touchBuffer: 25,
        displayControlsDefault: false,
        // styles, // 使用默认样式以支持编辑功能
        controls: {
          polygon: false,
          line_string: false,
          point: false,
          trash: false,
          combine_features: false,
          uncombine_features: false
        }
      })
      
      console.log('MapboxDraw instance created:', this.draw)
      
      this.map.addControl(this.draw)
      
      console.log('MapboxDraw added to map successfully')
      console.log('Testing draw mode:', this.draw.getMode())
      
      // Setup event listeners
      this.setupEventListeners()
      
      this.initialized = true
      
      
    } catch (error) {
      console.error('Failed to initialize MapboxDraw:', error)
      this.initialized = false
    }
  }

  setupEventListeners() {
    // Store bound functions for cleanup
    this._boundStartDrawing = this.startDrawing.bind(this)
    this._boundStopDrawing = this.stopDrawing.bind(this)
    this._boundOnDrawCreate = this.onDrawCreate.bind(this)
    this._boundOnDrawUpdate = this.onDrawUpdate.bind(this)
    this._boundOnDrawDelete = this.onDrawDelete.bind(this)
    this._boundOnSelectionChange = this.onSelectionChange.bind(this)
    this._boundHandleKeyDown = this.handleKeyDown.bind(this)
    
    // Listen for drawing mode activation from edit form
    emitter.on('START_MAP_DRAWING', this._boundStartDrawing)
    emitter.on('STOP_MAP_DRAWING', this._boundStopDrawing)
    
    // MapboxDraw events
    this.map.on('draw.create', this._boundOnDrawCreate)
    this.map.on('draw.update', this._boundOnDrawUpdate)
    this.map.on('draw.delete', this._boundOnDrawDelete)
    this.map.on('draw.selectionchange', this._boundOnSelectionChange)
    
    // Debug: listen to all draw events
    this.map.on('draw.modechange', (e) => {
      console.log('Draw mode changed:', e)
    })
    
    // Test if MapboxDraw is working
    console.log('Testing MapboxDraw - current mode:', this.draw.getMode())
    
    // Add click event listener to debug
    this.map.on('click', (e) => {
      console.log('Map clicked at:', e.lngLat, 'Current draw mode:', this.draw.getMode())
      console.log('isDrawingMode:', this.isDrawingMode)
      console.log('Draw instance exists:', !!this.draw)
      
      // Check if click is being handled by MapboxDraw
      const mode = this.draw.getMode()
      if (mode.startsWith('draw_')) {
        console.log('Should be drawing in mode:', mode)
      }
    })
    
    // Add keyboard event listener for delete key
    document.addEventListener('keydown', this._boundHandleKeyDown)
  }

  startDrawing(config) {
    console.log('DrawingManager.startDrawing called with config:', config)
    
    if (!this.initialized || !this.draw) {
      console.error('DrawingManager not properly initialized!')
      console.log('initialized:', this.initialized, 'draw:', this.draw)
      // Try to reinitialize if needed
      if (this.map && !this.draw) {
        console.log('Attempting to reinitialize DrawingManager...')
        this.init(this.map)
        // Wait a bit for initialization to complete
        setTimeout(() => {
          if (this.draw) {
            this.startDrawing(config)
          } else {
            Message.error('无法初始化绘制工具，请刷新页面重试')
          }
        }, 100)
      }
      return
    }
    
    this.isDrawingMode = true
    this.currentDrawingConfig = config
    
    // Disable other map click handlers during drawing
    emitter.emit('DISABLE_MAP_CLICK_HANDLERS')
    
    // Store and disable interactive layers
    this.disableOtherLayersInteraction()
    
    // Add draw mode class to map container
    if (this.map) {
      const container = this.map.getContainer()
      if (container) {
        container.classList.add('draw-mode-active')
      }
      
      // Ensure MapboxDraw layers are on top
      this.moveDrawLayersToTop()
      
      // Force map to update
      this.map.resize()
    }
    
    // Load existing data if any
    if (config.existingData) {
      console.log('Loading existing data:', config.existingData)
      this.loadExistingData(config.existingData)
    }
    
    // Show control buttons
    this.addControlButtons()
    
    // Set initial drawing mode or selection mode based on whether there's existing data
    console.log('Checking existingData:', config.existingData, 'Type:', typeof config.existingData)
    
    // Check if existingData is actually empty (null, undefined, empty string, empty object, etc.)
    let hasExistingData = false
    if (config.existingData) {
      if (typeof config.existingData === 'string') {
        hasExistingData = config.existingData.trim().length > 0
      } else if (typeof config.existingData === 'object') {
        // Check for GeoJSON Feature
        if (config.existingData.type === 'Feature' && config.existingData.geometry) {
          hasExistingData = true
        } else if (Object.keys(config.existingData).length > 0) {
          hasExistingData = true
        }
      } else {
        hasExistingData = true
      }
    }
    
    if (hasExistingData) {
      // If there's existing data, start in selection mode so user can edit
      console.log('Has existing data, switching to select mode')
      this.draw.changeMode('simple_select')
      Message.info('选择已有图形进行编辑，或点击"继续绘制"添加新图形')
    } else {
      // If no existing data, start drawing immediately
      console.log('No existing data, starting new drawing')
      this.startNewDrawing()
    }
    
    // Don't emit MAP_DRAWING_MODE_ACTIVE as it conflicts with map click handlers
    // emitter.emit('MAP_DRAWING_MODE_ACTIVE', true)
  }

  stopDrawing() {
    if (!this.draw) return
    
    this.isDrawingMode = false
    this.currentDrawingConfig = null
    
    // Remove draw mode class from map container
    if (this.map) {
      const container = this.map.getContainer()
      if (container) {
        container.classList.remove('draw-mode-active')
      }
    }
    
    // Remove control buttons if present
    this.removeControlButtons()
    
    // Clear all drawings
    this.draw.deleteAll()
    this.draw.changeMode('simple_select')
    
    // Re-enable other map click handlers
    emitter.emit('ENABLE_MAP_CLICK_HANDLERS')
    
    // Re-enable interactive layers
    this.enableOtherLayersInteraction()
    
    // Don't emit MAP_DRAWING_MODE_ACTIVE as it conflicts with map click handlers
    // emitter.emit('MAP_DRAWING_MODE_ACTIVE', false)
  }

  startNewDrawing() {
    if (!this.currentDrawingConfig) return
    
    const drawType = this.currentDrawingConfig.type
    console.log('Starting new drawing, type:', drawType)
    
    try {
      switch (drawType) {
        case 'line':
          this.draw.changeMode('draw_line_string')
          Message.info('开始绘制线条：点击地图添加点，双击或按Enter完成')
          break
        case 'polygon':
          this.draw.changeMode('draw_polygon')
          Message.info('开始绘制多边形：点击地图添加点，双击或按Enter完成')
          break
        case 'point':
          this.draw.changeMode('draw_point')
          Message.info('点击地图添加点位')
          break
        default:
          console.warn('Unknown draw type:', drawType)
          this.draw.changeMode('simple_select')
      }
      
      console.log('Draw mode changed to:', this.draw.getMode())
      
      // Verify the mode was set correctly
      const currentMode = this.draw.getMode()
      if (!currentMode.startsWith('draw_')) {
        console.error('Failed to enter drawing mode, current mode:', currentMode)
      }
      
    } catch (error) {
      console.error('Error starting new drawing:', error)
      Message.error('启动绘制模式失败')
    }
  }

  onDrawCreate(event) {
    console.log('onDrawCreate event triggered:', event)
    console.log('isDrawingMode:', this.isDrawingMode)
    console.log('currentDrawingConfig:', this.currentDrawingConfig)
    
    if (!this.isDrawingMode || !this.currentDrawingConfig) {
      console.log('Not in drawing mode or no config, returning')
      return
    }
    
    const feature = event.features[0]
    console.log('Created feature:', feature)
    
    // Delay mode change to avoid infinite recursion
    requestAnimationFrame(() => {
      // For point mode, continue drawing more points
      if (this.currentDrawingConfig.type === 'point') {
        setTimeout(() => {
          if (this.draw && this.isDrawingMode) {
            this.draw.changeMode('draw_point')
          }
        }, 100)
      } else {
        // For line and polygon, switch to select mode after creating one
        if (this.draw) {
          this.draw.changeMode('simple_select')
          Message.success('绘制完成，可选择图形进行编辑或点击"继续绘制"')
        }
      }
    })
  }

  onDrawUpdate(event) {
    if (!this.isDrawingMode || !this.currentDrawingConfig) return
    // Drawing was updated (edited)
  }

  onDrawDelete(event) {
    if (!this.isDrawingMode || !this.currentDrawingConfig) return
    Message.info('已删除选中的图形')
  }

  onSelectionChange(event) {
    if (!this.isDrawingMode || !this.currentDrawingConfig) return
    
    // Update delete button state based on selection
    const deleteBtn = this.controlsContainer?.querySelector('.delete-btn')
    if (deleteBtn) {
      deleteBtn.disabled = event.features.length === 0
      deleteBtn.style.opacity = event.features.length === 0 ? '0.5' : '1'
      deleteBtn.style.cursor = event.features.length === 0 ? 'not-allowed' : 'pointer'
    }
  }

  handleKeyDown(event) {
    if (!this.isDrawingMode || !this.draw) return
    
    // Delete key to remove selected features
    if (event.key === 'Delete' || event.key === 'Backspace') {
      const selectedFeatures = this.draw.getSelected()
      if (selectedFeatures.features.length > 0) {
        const selectedIds = selectedFeatures.features.map(f => f.id)
        this.draw.delete(selectedIds)
        event.preventDefault()
      }
    }
    
    // ESC key to cancel current drawing
    if (event.key === 'Escape') {
      // If currently drawing, cancel the current drawing
      const currentMode = this.draw.getMode()
      if (currentMode === 'draw_line_string' || currentMode === 'draw_polygon' || currentMode === 'draw_point') {
        this.draw.changeMode('simple_select')
        Message.info('已取消当前绘制')
      }
      event.preventDefault()
    }
  }

  loadExistingData(data) {
    if (!data || !this.draw) return
    
    console.log('Loading existing data into draw:', data)
    
    try {
      // Clear existing features first
      this.draw.deleteAll()
      
      // If it's a GeoJSON Feature, add it directly
      if (data.type === 'Feature') {
        // If it's a multi-geometry, split it into individual features
        const geometry = data.geometry
        if (geometry.type === 'MultiLineString') {
          geometry.coordinates.forEach((coords, index) => {
            const feature = {
              type: 'Feature',
              properties: {},
              geometry: {
                type: 'LineString',
                coordinates: coords
              }
            }
            this.draw.add(feature)
            console.log(`Added line ${index + 1}:`, feature)
          })
        } else if (geometry.type === 'MultiPolygon') {
          geometry.coordinates.forEach((coords, index) => {
            const feature = {
              type: 'Feature',
              properties: {},
              geometry: {
                type: 'Polygon',
                coordinates: coords
              }
            }
            this.draw.add(feature)
            console.log(`Added polygon ${index + 1}:`, feature)
          })
        } else if (geometry.type === 'MultiPoint') {
          geometry.coordinates.forEach((coords, index) => {
            const feature = {
              type: 'Feature',
              properties: {},
              geometry: {
                type: 'Point',
                coordinates: coords
              }
            }
            this.draw.add(feature)
            console.log(`Added point ${index + 1}:`, feature)
          })
        } else {
          // Single geometry
          this.draw.add(data)
          console.log('Added single feature:', data)
        }
        
        // Log all features after loading
        const allFeatures = this.draw.getAll()
        console.log('All features after loading:', allFeatures)
      }
    } catch (error) {
      console.error('Failed to load existing drawing data:', error)
    }
  }

  saveDrawing() {
    if (!this.currentDrawingConfig) return
    
    const allFeatures = this.draw.getAll()
    const features = allFeatures.features
    
    if (features.length === 0) {
      emitter.emit('MAP_DRAWING_COMPLETE', {
        itemId: this.currentDrawingConfig.itemId,
        geoJsonFeature: null,
        featureCount: 0,
        positionInfo: '未绘制'
      })
      return
    }
    
    let geoJsonFeature = null
    let featureCount = 0
    let positionInfo = ''
    
    // Group features by type
    const lines = features.filter(f => f.geometry.type === 'LineString')
    const polygons = features.filter(f => f.geometry.type === 'Polygon')
    const points = features.filter(f => f.geometry.type === 'Point')
    
    switch (this.currentDrawingConfig.type) {
      case 'line':
        if (lines.length === 1) {
          geoJsonFeature = lines[0]
        } else if (lines.length > 1) {
          // Combine multiple lines into MultiLineString
          geoJsonFeature = {
            type: 'Feature',
            properties: {},
            geometry: {
              type: 'MultiLineString',
              coordinates: lines.map(f => f.geometry.coordinates)
            }
          }
        }
        featureCount = lines.length
        positionInfo = `${featureCount} 条线`
        break
        
      case 'polygon':
        if (polygons.length === 1) {
          geoJsonFeature = polygons[0]
        } else if (polygons.length > 1) {
          // Combine multiple polygons into MultiPolygon
          geoJsonFeature = {
            type: 'Feature',
            properties: {},
            geometry: {
              type: 'MultiPolygon',
              coordinates: polygons.map(f => f.geometry.coordinates)
            }
          }
        }
        featureCount = polygons.length
        positionInfo = `${featureCount} 个面`
        break
        
      case 'point':
        if (points.length === 1) {
          geoJsonFeature = points[0]
        } else if (points.length > 1) {
          // Combine multiple points into MultiPoint
          geoJsonFeature = {
            type: 'Feature',
            properties: {},
            geometry: {
              type: 'MultiPoint',
              coordinates: points.map(f => f.geometry.coordinates)
            }
          }
        }
        featureCount = points.length
        positionInfo = `${featureCount} 个点`
        break
    }
    
    // Emit the result
    emitter.emit('MAP_DRAWING_COMPLETE', {
      itemId: this.currentDrawingConfig.itemId,
      geoJsonFeature,
      featureCount,
      positionInfo
    })
    
    Message.success(`保存成功: ${positionInfo}`)
    
    // Clean up but keep the data on map for user reference
    this.cleanupAfterSave()
  }

  cleanupAfterSave() {
    // Keep drawing mode active but clean up UI
    this.removeControlButtons()
    
    // Remove draw mode class from map container
    if (this.map) {
      const container = this.map.getContainer()
      if (container) {
        container.classList.remove('draw-mode-active')
      }
    }
    
    // Clear all drawings from the map
    this.draw.deleteAll()
    this.draw.changeMode('simple_select')
    
    // Clean up state
    this.isDrawingMode = false
    this.currentDrawingConfig = null
    
    // Re-enable map click handlers
    emitter.emit('ENABLE_MAP_CLICK_HANDLERS')
    
    // Re-enable interactive layers
    this.enableOtherLayersInteraction()
  }

  deleteSelected() {
    const selectedFeatures = this.draw.getSelected()
    if (selectedFeatures.features.length > 0) {
      const selectedIds = selectedFeatures.features.map(f => f.id)
      this.draw.delete(selectedIds)
    } else {
      Message.warning('请先选择要删除的图形')
    }
  }

  clearAll() {
    const allFeatures = this.draw.getAll()
    if (allFeatures.features.length > 0) {
      this.draw.deleteAll()
      Message.info('已清除所有绘制')
    } else {
      Message.info('没有可清除的内容')
    }
  }

  // Add control buttons to the map
  addControlButtons() {
    console.log('addControlButtons called')
    
    // Remove existing controls if any
    if (this.controlsContainer) {
      console.log('Removing existing control buttons')
      this.removeControlButtons()
    }
    
    // Create button container
    const container = document.createElement('div')
    container.className = 'map-drawing-controls'
    container.style.cssText = `
      position: absolute;
      top: 10px;
      right: 50px;
      z-index: 1000;
      display: flex;
      gap: 10px;
      background: white;
      padding: 10px;
      border-radius: 8px;
      box-shadow: 0 2px 10px rgba(0,0,0,0.2);
    `
    
    // Create save button
    const saveBtn = this.createButton('保存绘制', '#1890ff', () => {
      this.saveDrawing()
    })
    
    // Create continue drawing button for line and polygon
    let continueBtn = null
    if (this.currentDrawingConfig.type !== 'point') {
      continueBtn = this.createButton('继续绘制', '#52c41a', () => {
        console.log('Continue drawing button clicked')
        this.startNewDrawing()
      })
    }
    
    // Create delete selected button
    const deleteBtn = this.createButton('删除选中', '#faad14', () => {
      this.deleteSelected()
    })
    deleteBtn.classList.add('delete-btn')
    deleteBtn.disabled = true
    deleteBtn.style.opacity = '0.5'
    deleteBtn.style.cursor = 'not-allowed'
    
    // Create clear all button
    const clearBtn = this.createButton('清除全部', '#ff7875', () => {
      this.clearAll()
    })
    
    // Create cancel button
    const cancelBtn = this.createButton('取消', '#8c8c8c', () => {
      this.stopDrawing()
      Message.info('已取消绘制')
    })
    
    // Add buttons to container
    container.appendChild(saveBtn)
    if (continueBtn) {
      container.appendChild(continueBtn)
    }
    container.appendChild(deleteBtn)
    container.appendChild(clearBtn)
    container.appendChild(cancelBtn)
    
    // Add container to map
    if (this.map && this.map.getContainer()) {
      this.map.getContainer().appendChild(container)
      this.controlsContainer = container
      console.log('Control buttons added to map')
    } else {
      console.error('Cannot add control buttons - map or container not available')
    }
  }

  createButton(text, color, onClick) {
    const btn = document.createElement('button')
    btn.innerHTML = text
    btn.style.cssText = `
      padding: 8px 16px;
      background: ${color};
      color: white;
      border: none;
      border-radius: 4px;
      cursor: pointer;
      font-size: 14px;
      transition: all 0.3s;
      white-space: nowrap;
    `
    
    btn.onmouseover = () => {
      if (!btn.disabled) {
        btn.style.transform = 'translateY(-1px)'
        btn.style.boxShadow = '0 4px 8px rgba(0,0,0,0.15)'
      }
    }
    
    btn.onmouseout = () => {
      btn.style.transform = 'translateY(0)'
      btn.style.boxShadow = 'none'
    }
    
    btn.onclick = onClick
    
    return btn
  }

  // Remove control buttons
  removeControlButtons() {
    if (this.controlsContainer) {
      this.controlsContainer.remove()
      this.controlsContainer = null
    }
  }

  cleanup() {
    console.log('DrawingManager.cleanup called')
    
    // Remove control buttons first
    this.removeControlButtons()
    
    // Remove MapboxDraw control
    if (this.draw && this.map) {
      try {
        this.map.removeControl(this.draw)
      } catch (e) {
        console.error('Error removing draw control:', e)
      }
      this.draw = null
    }
  }
  
  destroy() {
    console.log('DrawingManager.destroy called')
    
    // Use cleanup method
    this.cleanup()
    
    // Remove event listeners using stored bound functions
    if (this._boundStartDrawing) {
      emitter.off('START_MAP_DRAWING', this._boundStartDrawing)
      emitter.off('STOP_MAP_DRAWING', this._boundStopDrawing)
    }
    
    if (this._boundHandleKeyDown) {
      document.removeEventListener('keydown', this._boundHandleKeyDown)
    }
    
    if (this.map && this._boundOnDrawCreate) {
      this.map.off('draw.create', this._boundOnDrawCreate)
      this.map.off('draw.update', this._boundOnDrawUpdate)
      this.map.off('draw.delete', this._boundOnDrawDelete)
      this.map.off('draw.selectionchange', this._boundOnSelectionChange)
    }
    
    // Clear references
    this.map = null
    this.isDrawingMode = false
    this.currentDrawingConfig = null
    
    // Reset initialization flag
    this.initialized = false
  }
  
  moveDrawLayersToTop() {
    console.log('Moving draw layers to top')
    
    if (!this.map || !this.draw) return
    
    // Get all layers
    const layers = this.map.getStyle().layers
    
    // Find all MapboxDraw layers
    const drawLayerIds = [
      'gl-draw-polygon-fill-inactive',
      'gl-draw-polygon-fill-active',
      'gl-draw-polygon-stroke-inactive',
      'gl-draw-polygon-stroke-active',
      'gl-draw-line-inactive',
      'gl-draw-line-active',
      'gl-draw-point-inactive',
      'gl-draw-point-active',
      'gl-draw-polygon-midpoint',
      'gl-draw-vertex-inactive',
      'gl-draw-vertex-active'
    ]
    
    // Move each draw layer to the top
    try {
      drawLayerIds.forEach(layerId => {
        if (this.map.getLayer(layerId)) {
          this.map.moveLayer(layerId)
          console.log(`Moved ${layerId} to top`)
        }
      })
    } catch (error) {
      console.error('Error moving draw layers:', error)
    }
  }
  
  disableOtherLayersInteraction() {
    if (!this.map) return
    
    console.log('Disabling other layers interaction')
    
    // Store interactive layers state
    this.interactiveLayers = []
    
    const layers = this.map.getStyle().layers
    layers.forEach(layer => {
      // Skip MapboxDraw layers
      if (layer.id.includes('gl-draw')) return
      
      // Check if layer is interactive (has click events)
      const listeners = this.map._listeners
      if (listeners && listeners.click) {
        const hasClickListener = listeners.click.some(listener => {
          return listener.layer === layer.id
        })
        
        if (hasClickListener) {
          this.interactiveLayers.push(layer.id)
        }
      }
    })
    
    console.log('Found interactive layers:', this.interactiveLayers)
    
    // Temporarily remove click handlers for these layers
    this.interactiveLayers.forEach(layerId => {
      try {
        // Store the layer's paint properties
        const fillOpacity = this.map.getPaintProperty(layerId, 'fill-opacity')
        if (fillOpacity !== undefined) {
          // Slightly reduce opacity to indicate non-interactive state
          this.map.setPaintProperty(layerId, 'fill-opacity', fillOpacity * 0.7)
        }
      } catch (e) {
        // Layer might not have fill-opacity
      }
    })
    
    // Emit event to notify that we're in drawing mode
    emitter.emit('DRAWING_MODE_ACTIVE', true)
  }
  
  enableOtherLayersInteraction() {
    if (!this.map || !this.interactiveLayers) return
    
    console.log('Re-enabling other layers interaction')
    
    // Restore opacity for interactive layers
    this.interactiveLayers.forEach(layerId => {
      try {
        const fillOpacity = this.map.getPaintProperty(layerId, 'fill-opacity')
        if (fillOpacity !== undefined) {
          // Restore original opacity
          this.map.setPaintProperty(layerId, 'fill-opacity', fillOpacity / 0.7)
        }
      } catch (e) {
        // Layer might not have fill-opacity
      }
    })
    
    // Clear the stored layers
    this.interactiveLayers = []
    
    // Emit event to notify that drawing mode is inactive
    emitter.emit('DRAWING_MODE_ACTIVE', false)
  }
  
}

export default DrawingManager